package com.crm.business.crm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.crm.business.admin.service.AdminFileService;
import com.crm.business.admin.service.AdminService;
import com.crm.business.crm.mapper.CrmContactsMapper;
import com.crm.business.crm.service.*;
import com.crm.business.utils.ActionRecordUtil;
import com.crm.business.utils.AuthUtil;
import com.crm.common.crm.common.*;
import com.crm.common.crm.constant.CrmActivityEnum;
import com.crm.common.crm.constant.CrmCodeEnum;
import com.crm.common.crm.constant.CrmEnum;
import com.crm.common.crm.constant.FieldEnum;
import com.crm.common.crm.entity.BO.*;
import com.crm.common.crm.entity.PO.*;
import com.crm.common.crm.entity.VO.CrmDataCheckVO;
import com.crm.common.crm.entity.VO.CrmFieldSortVO;
import com.crm.common.crm.entity.VO.CrmInfoNumVO;
import com.crm.common.crm.entity.VO.CrmModelFiledVO;
import com.crm.common.ka.core.common.Const;
import com.crm.common.ka.core.common.SystemCodeEnum;
import com.crm.common.ka.core.common.log.BehaviorEnum;
import com.crm.common.ka.core.entity.BasePage;
import com.crm.common.ka.core.exception.CrmException;
import com.crm.common.crm.entity.BO.CrmSearchBO;
import com.crm.common.ka.core.feign.crm.entity.SimpleCrmEntity;
import com.crm.business.servlet.ApplicationContextHolder;
import com.crm.business.servlet.BaseServiceImpl;
import com.crm.common.ka.core.servlet.upload.FileEntity;
import com.crm.business.utils.UserCacheUtil;
import com.crm.business.utils.UserUtil;
import com.crm.common.utils.StringUtils;
import com.crm.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 联系人表 服务实现类
 * </p>
 *
 * @author zhangzhiwei
 * @since 2020-05-26
 */
@Service
@Slf4j
public class CrmContactsServiceImpl extends BaseServiceImpl<CrmContactsMapper, CrmContacts> implements ICrmContactsService, CrmPageService {

    @Autowired
    private ICrmFieldService crmFieldService;

    @Autowired
    private ICrmContactsDataService crmContactsDataService;

    @Autowired
    private ICrmActivityService crmActivityService;

    @Autowired
    private ICrmActionRecordService crmActionRecordService;

    @Autowired
    private ICrmContactsBusinessService crmContactsBusinessService;

    @Autowired
    private ICrmContactsUserStarService crmContactsUserStarService;

    @Autowired
    private ICrmCustomerService crmCustomerService;

    @Autowired
    private ActionRecordUtil actionRecordUtil;

    @Autowired
    private AdminService adminService;

    @Autowired
    private AdminFileService adminFileService;

    @Autowired
    private ICrmBusinessService crmBusinessService;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 查询字段配置
     *
     * @param id 主键ID
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryField(Integer id) {
        CrmModel crmModel = queryById(id);

        //编辑回显设置客户数据
        if (id != null) {
            List<JSONObject> customerList = new ArrayList<>();
            if (crmModel.get("customerId") != null) {
                JSONObject customer = new JSONObject();
                customerList.add(customer.fluentPut("customerId", crmModel.get("customerId")).fluentPut("customerName", crmModel.get("customerName")));
            }
            crmModel.put("customerId", customerList);
        }

        List<CrmModelFiledVO> vos = crmFieldService.queryField(crmModel);

        JSONObject value = new JSONObject();
        value.put("address", crmModel.get("address"));
        if (crmModel.get("address") != null) {
            LinkedHashMap addressVal = JSON.parseObject(crmModel.get("address").toString(), LinkedHashMap.class);
            vos.add(new CrmModelFiledVO("map_address", FieldEnum.ADDRESS, "省/市/区", 1).setIsNull(0).setValue(addressVal));
        } else {
            LinkedHashMap addressVal = null;
            vos.add(new CrmModelFiledVO("map_address", FieldEnum.ADDRESS, "省/市/区", 1).setIsNull(0).setValue(addressVal));
        }

        vos.removeIf(field -> field.getFieldName().equals("currentCity"));
        if (crmModel.get("currentCity") != null) {
            LinkedHashMap addressVal = JSON.parseObject(crmModel.get("currentCity").toString(), LinkedHashMap.class);
            vos.add(new CrmModelFiledVO("map_city", FieldEnum.ADDRESS, "目前就业城市", 1).setIsNull(0).setValue(addressVal));
        } else {
            LinkedHashMap addressVal = null;
//            vos.removeIf(field -> field.getFieldName().equals("currentCity"));
            vos.add(new CrmModelFiledVO("map_city", FieldEnum.ADDRESS, "目前就业城市", 1).setIsNull(0).setValue(addressVal));
        }

//        vos.removeIf(field -> field.getFieldName().equals("fliedWifsuu"));
//        if (crmModel.get("fliedWifsuu") != null) {
//            LinkedHashMap addressVal = JSON.parseObject(crmModel.get("fliedWifsuu").toString(), LinkedHashMap.class);
//            vos.add(new CrmModelFiledVO("map_Wifsuu", FieldEnum.ADDRESS, "期望就业城市", 1).setIsNull(0).setValue(addressVal));
//        } else {
//            LinkedHashMap addressVal = null;
////            vos.removeIf(field -> field.getFieldName().equals("currentCity"));
//            vos.add(new CrmModelFiledVO("map_Wifsuu", FieldEnum.ADDRESS, "期望就业城市", 1).setIsNull(0).setValue(addressVal));
//        }

        vos.removeIf(field -> field.getFieldName().equals("contactsDataType"));

        return vos;
    }

    /**
     * 分页查询
     *
     * @param search search
     * @return data
     */
    @Override
    public BasePage<Map<String, Object>> queryPageList(CrmSearchBO search) {
        BasePage<Map<String, Object>> basePage = queryList(search);
        Long userId = UserUtil.getUserId();
        List<Integer> starIds = crmContactsUserStarService.starList(userId);
        basePage.getList().forEach(map -> {
            map.put("star", starIds.contains((Integer) map.get("contactsId")) ? 1 : 0);
        });
        return basePage;
    }

    /**
     * 查询字段配置
     *
     * @param id 主键ID
     * @return data
     */
    @Override
    public CrmModel queryById(Integer id) {
        CrmModel crmModel;
        if (id != null) {
            crmModel = getBaseMapper().queryById(id, UserUtil.getUserId());
            crmModel.setLabel(CrmEnum.CONTACTS.getType());
            crmModel.setOwnerUserName(UserCacheUtil.getUserName(crmModel.getOwnerUserId()));
            crmContactsDataService.setDataByBatchId(crmModel);
            List<String> stringList = SpringUtils.getBean(ICrmRoleFieldService.class).queryNoAuthField(crmModel.getLabel());
            List<String> deptFieldList = SpringUtils.getBean(ICrmDeptFieldService.class).queryNoAuthField(crmModel.getLabel());
            stringList = stringList.stream().filter(field -> deptFieldList.contains(field)).collect(Collectors.toList());
            stringList = stringList.stream().distinct().collect(Collectors.toList());
//            stringList.forEach(crmModel::remove);
        } else {
            crmModel = new CrmModel(CrmEnum.CONTACTS.getType());
        }
        return crmModel;
    }

    /**
     * 保存或新增信息
     *
     * @param crmModel model
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdate(CrmContactsSaveBO crmModel, boolean isExcel) {
        CrmContacts crmContacts = BeanUtil.copyProperties(crmModel.getEntity(), CrmContacts.class);
        String batchId = StrUtil.isNotEmpty(crmContacts.getBatchId()) ? crmContacts.getBatchId() : IdUtil.simpleUUID();
        actionRecordUtil.updateRecord(crmModel.getField(), Dict.create().set("batchId", batchId).set("dataTableName", "bill_crm_contacts_data"));
        crmContactsDataService.saveData(crmModel.getField(), batchId);
        if (StrUtil.isEmpty(crmContacts.getEmail())) {
            crmContacts.setEmail(null);
        }

        if (crmContacts.getContactsId() != null) {
            CrmContacts oldCrmContacts = getById(crmContacts.getContactsId());
            //修改时  更换的客户如果已绑定联系人
            if (!oldCrmContacts.getCustomerId().equals(crmContacts.getCustomerId())) {
                Integer contactsNum = getCustomerNumber(crmContacts.getCustomerId());
                if (contactsNum > 0) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_BIND_CUSTOMER_MORE_THAN_ONE);
                }
            }
        } else {
            //新增 如果客户已绑定联系人
            Integer contactsNum = getCustomerNumber(crmContacts.getCustomerId());
            if (contactsNum > 0) {
                throw new CrmException(CrmCodeEnum.CRM_CONTACTS_BIND_CUSTOMER_MORE_THAN_ONE);
            }
        }

        //验证电话格式
        if(StringUtils.isNotBlank(crmContacts.getTelephone())){
            if(!(crmContacts.getTelephone().matches(Const.REG_EXP_MOBILE) || crmContacts.getTelephone().matches(Const.REG_EXP_TELEPHONE))){
                throw new CrmException(CrmCodeEnum.CRM_REG_EXP_ERROR);
            }
        }
        if (crmContacts.getContactsId() != null) {
            if ("是".equals(crmContacts.getRefunding())) {
                if (StringUtils.isBlank(crmContacts.getTurnEarlyNumber())) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_REFUNDING_IS_TRUE_NUMBER_NEED);
                }
            } else {
                crmContacts.setTurnEarlyNumber(StringUtils.EMPTY);
            }
            if ("是".equals(crmContacts.getTurnIntroduce())) {
                if (StringUtils.isBlank(crmContacts.getTurnReferral())) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_TURN_INTRODUCE_IS_TRUE_NUMBER_NEED);
                }
            } else {
                crmContacts.setTurnReferral(StringUtils.EMPTY);
            }

            //查询客户编号进行设置
            CrmCustomer customer = crmCustomerService.getById(crmContacts.getCustomerId());
            crmContacts.setSerialNumber(customer.getSerialNumber());

            actionRecordUtil.updateRecord(BeanUtil.beanToMap(getById(crmContacts.getContactsId())), BeanUtil.beanToMap(crmContacts), CrmEnum.CONTACTS, crmContacts.getName(), crmContacts.getContactsId());
            crmContacts.setUpdateTime(DateUtil.date());
            updateById(crmContacts);
            crmContacts = getById(crmContacts);
            ElasticUtil.batchUpdateEsData(elasticsearchRestTemplate.getClient(), "contacts", crmContacts.getContactsId().toString(), crmContacts.getName());
        } else {
            if ("是".equals(crmContacts.getRefunding())) {
                if (StringUtils.isBlank(crmContacts.getTurnEarlyNumber())) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_REFUNDING_IS_TRUE_NUMBER_NEED);
                }
            }
            if ("是".equals(crmContacts.getTurnIntroduce())) {
                if (StringUtils.isBlank(crmContacts.getTurnReferral())) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_TURN_INTRODUCE_IS_TRUE_NUMBER_NEED);
                }
            }

            //新增联系人时设置联系人的回款状态
            String crmContractBackStatus = SpringUtils.getBean(ICrmContractService.class).queryContractByCustomerId(crmContacts.getCustomerId());
            if (StringUtils.isNotEmpty(crmContractBackStatus)) {
                if (crmContractBackStatus.contains("已回款")) {
                    crmContacts.setBackStatus("已回款");
                }
                if (crmContractBackStatus.contains("回款中")) {
                    crmContacts.setBackStatus("回款中");
                }
                if (crmContractBackStatus.contains("未回款")) {
                    crmContacts.setBackStatus("未回款");
                }
            } else {
                crmContacts.setBackStatus("未回款");
            }

            //查询客户编号进行设置
            CrmCustomer customer = crmCustomerService.getById(crmContacts.getCustomerId());
            crmContacts.setSerialNumber(customer.getSerialNumber());

            crmContacts.setCreateTime(DateUtil.date());
            crmContacts.setUpdateTime(DateUtil.date());
            crmContacts.setCreateUserId(UserUtil.getUserId());
            if (crmContacts.getOwnerUserId() == null) {
                crmContacts.setOwnerUserId(UserUtil.getUserId());
            }
            crmContacts.setBatchId(batchId);
            if (crmContacts.getCustomerId() == null) {
                throw new CrmException(CrmCodeEnum.CRM_CONTACTS_DATA_ERROR);
            }

            //设置新老数据字段值为新数据：有成：代表旧数据；涵品：代表新数据
            crmContacts.setDataFrom("涵品");
            crmContacts.setContactsDataType("正常关联");

            save(crmContacts);
            if (crmModel.getBusinessId() != null) {
                crmContactsBusinessService.save(crmModel.getBusinessId(), crmContacts.getContactsId());
            }
            crmActivityService.addActivity(2, CrmActivityEnum.CONTACTS, crmContacts.getContactsId());
            actionRecordUtil.addRecord(crmContacts.getContactsId(), CrmEnum.CONTACTS, crmContacts.getName());
        }
        ICrmCustomerService bean = SpringUtils.getBean(ICrmCustomerService.class);
        CrmCustomer customer = bean.getById(crmContacts.getCustomerId());
        if (customer != null && customer.getContactsId() == null) {
            customer.setContactsId(crmContacts.getContactsId());
            bean.updateById(customer);
        }
        crmModel.setEntity(BeanUtil.beanToMap(crmContacts));
        savePage(crmModel, crmContacts.getContactsId(), isExcel);
    }

    /**
     * 保存或新增信息
     *
     * @param crmModel model
     */
    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdateToImport(CrmContactsSaveBO crmModel, boolean isExcel) {

        List<CrmModelFiledVO> crmModelField = crmModel.getField();
        for(int i=0;i<crmModelField.size();i++){
            if("mapAddress".equals(crmModelField.get(i).getFieldName()) || "mapCity".equals(crmModelField.get(i).getFieldName())){
                crmModel.getField().remove(i);
            }
            /*if("mapCity".equals(crmModelField.get(i).getFieldName())){
                cityIndex = i;
            }*/
            if("customerId".equals(crmModelField.get(i).getFieldName())){
                crmModelField.get(i).setValue(crmModel.getEntity().get("customerId"));
            }
        }

//        crmModel.getField().remove(40);

        CrmContacts crmContacts = BeanUtil.copyProperties(crmModel.getEntity(), CrmContacts.class);
        String batchId = StrUtil.isNotEmpty(crmContacts.getBatchId()) ? crmContacts.getBatchId() : IdUtil.simpleUUID();
        actionRecordUtil.updateRecord(crmModel.getField(), Dict.create().set("batchId", batchId).set("dataTableName", "bill_crm_contacts_data"));
        crmContactsDataService.saveData(crmModel.getField(), batchId);
        if (StrUtil.isEmpty(crmContacts.getEmail())) {
            crmContacts.setEmail(null);
        }

        //验证电话格式
        if(StringUtils.isNotBlank(crmContacts.getTelephone().trim())){
            if(!(crmContacts.getTelephone().trim().matches(Const.REG_EXP_MOBILE) || crmContacts.getTelephone().trim().matches(Const.REG_EXP_TELEPHONE))){
                throw new CrmException(CrmCodeEnum.CRM_REG_EXP_ERROR);
            }
        }

        //根究系统编号获取联系人
        Integer contactsId = baseMapper.queryContactsIdBySerialNumber(crmContacts.getSerialNumber());
        if(BeanUtil.isNotEmpty(contactsId)){
            crmContacts.setContactsId(contactsId);
        }

        if (crmContacts.getContactsId() != null) {
            if ("是".equals(crmContacts.getRefunding())) {
                if (StringUtils.isBlank(crmContacts.getTurnEarlyNumber())) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_REFUNDING_IS_TRUE_NUMBER_NEED);
                }
            } else {
                crmContacts.setTurnEarlyNumber(StringUtils.EMPTY);
            }
            if ("是".equals(crmContacts.getTurnIntroduce())) {
                if (StringUtils.isBlank(crmContacts.getTurnReferral())) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_TURN_INTRODUCE_IS_TRUE_NUMBER_NEED);
                }
            } else {
                crmContacts.setTurnReferral(StringUtils.EMPTY);
            }

            //查询客户编号进行设置
            CrmCustomer customer = crmCustomerService.getById(crmContacts.getCustomerId());
            crmContacts.setSerialNumber(customer.getSerialNumber());

            actionRecordUtil.updateRecord(BeanUtil.beanToMap(getById(crmContacts.getContactsId())), BeanUtil.beanToMap(crmContacts), CrmEnum.CONTACTS, crmContacts.getName(), crmContacts.getContactsId());
            crmContacts.setUpdateTime(DateUtil.date());
            updateById(crmContacts);
            crmContacts = getById(crmContacts);
            ElasticUtil.batchUpdateEsData(elasticsearchRestTemplate.getClient(), "contacts", crmContacts.getContactsId().toString(), crmContacts.getName());
        } else {
            if ("是".equals(crmContacts.getRefunding())) {
                if (StringUtils.isBlank(crmContacts.getTurnEarlyNumber())) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_REFUNDING_IS_TRUE_NUMBER_NEED);
                }
            }
            if ("是".equals(crmContacts.getTurnIntroduce())) {
                if (StringUtils.isBlank(crmContacts.getTurnReferral())) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_TURN_INTRODUCE_IS_TRUE_NUMBER_NEED);
                }
            }

            //新增联系人时设置联系人的回款状态
            String crmContractBackStatus = SpringUtils.getBean(ICrmContractService.class).queryContractByCustomerId(crmContacts.getCustomerId());
            if (StringUtils.isNotEmpty(crmContractBackStatus)) {
                if (crmContractBackStatus.contains("已回款")) {
                    crmContacts.setBackStatus("已回款");
                }
                if (crmContractBackStatus.contains("回款中")) {
                    crmContacts.setBackStatus("回款中");
                }
                if (crmContractBackStatus.contains("未回款")) {
                    crmContacts.setBackStatus("未回款");
                }
            } else {
                crmContacts.setBackStatus("未回款");
            }

            //查询客户编号进行设置
            CrmCustomer customer = crmCustomerService.getById(crmContacts.getCustomerId());
            crmContacts.setSerialNumber(customer.getSerialNumber());

            crmContacts.setCreateTime(DateUtil.date());
            crmContacts.setUpdateTime(DateUtil.date());
            crmContacts.setCreateUserId(UserUtil.getUserId());
            if (crmContacts.getOwnerUserId() == null) {
                crmContacts.setOwnerUserId(UserUtil.getUserId());
            }
            crmContacts.setBatchId(batchId);
            if (crmContacts.getCustomerId() == null) {
                throw new CrmException(CrmCodeEnum.CRM_CONTACTS_DATA_ERROR);
            }

            //设置新老数据字段值为新数据：有成：代表旧数据；涵品：代表新数据
            crmContacts.setDataFrom("涵品");
            crmContacts.setContactsDataType("正常关联");

            save(crmContacts);
            if (crmModel.getBusinessId() != null) {
                crmContactsBusinessService.save(crmModel.getBusinessId(), crmContacts.getContactsId());
            }
            crmActivityService.addActivity(2, CrmActivityEnum.CONTACTS, crmContacts.getContactsId());
            actionRecordUtil.addRecord(crmContacts.getContactsId(), CrmEnum.CONTACTS, crmContacts.getName());
        }
        ICrmCustomerService bean = SpringUtils.getBean(ICrmCustomerService.class);
        CrmCustomer customer = bean.getById(crmContacts.getCustomerId());
        if (customer != null && customer.getContactsId() == null) {
            customer.setContactsId(crmContacts.getContactsId());
            bean.updateById(customer);
        }
        crmModel.setEntity(BeanUtil.beanToMap(crmContacts));
        savePage(crmModel, crmContacts.getContactsId(), isExcel);
    }

    public Integer getCustomerNumber(Integer customerId) {
        Integer contractNum = lambdaQuery().eq(CrmContacts::getCustomerId, customerId).count();
        return contractNum;
    }

    @Override
    public void setOtherField(Map<String, Object> map) {
        String ownerUserName = UserCacheUtil.getUserName((Long) map.get("ownerUserId"));
        map.put("ownerUserName", ownerUserName);
        String createUserName = UserCacheUtil.getUserName((Long) map.get("createUserId"));
        map.put("createUserName", createUserName);
        String customerName = crmCustomerService.getCustomerName((Integer) map.get("customerId"));
        map.put("customerName", customerName);
    }

    @Override
    public Dict getSearchTransferMap() {
        return Dict.create().set("customerId", "customerName");
    }

    /**
     * 删除联系人数据
     *
     * @param ids ids
     */
    @Override
    public void deleteByIds(List<Integer> ids) {
        for (Integer id : ids) {
            Integer count = SpringUtils.getBean(ICrmContractService.class).lambdaQuery().eq(CrmContract::getContactsId, id).ne(CrmContract::getCheckStatus, 7).count();
            if (count > 0) {
                throw new CrmException(CrmCodeEnum.CRM_DATA_JOIN_ERROR);
            }
            CrmContacts contacts = getById(id);
            if (contacts != null) {
                //删除自定义字段
                crmContactsBusinessService.removeByContactsId(id);
                LambdaUpdateWrapper<CrmCustomer> wrapper = new LambdaUpdateWrapper<>();
                wrapper.set(CrmCustomer::getContactsId, null).eq(CrmCustomer::getContactsId, contacts.getContactsId());
                SpringUtils.getBean(ICrmCustomerService.class).update(wrapper);
                LambdaUpdateWrapper<CrmBusiness> businessLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                businessLambdaUpdateWrapper.set(CrmBusiness::getContactsId, null).eq(CrmBusiness::getContactsId, contacts.getContactsId());
                SpringUtils.getBean(ICrmBusinessService.class).update(businessLambdaUpdateWrapper);
                //删除跟进记录
                crmActivityService.deleteActivityRecord(CrmActivityEnum.CONTACTS, Collections.singletonList(contacts.getContactsId()));
                //删除字段操作记录
                crmActionRecordService.deleteActionRecord(CrmEnum.CONTACTS, Collections.singletonList(contacts.getContactsId()));
                //删除联系人商机关联
                SpringUtils.getBean(ICrmContactsBusinessService.class).removeByContactsId(id);
                //删除自定义字段
                crmContactsDataService.deleteByBatchId(Collections.singletonList(contacts.getBatchId()));
                removeById(id);
            }
        }
        deletePage(ids);
    }

    /**
     * 修改联系人负责人
     *
     * @param ids            联系人id列表
     * @param newOwnerUserId 新负责人ID
     */
    @Override
    public void changeOwnerUser(List<Integer> ids, Long newOwnerUserId) {
        if (ids.size() == 0) {
            return;
        }
        for (Integer id : ids) {
            if (AuthUtil.isRwAuth(id, CrmEnum.CONTACTS)) {
                throw new CrmException(SystemCodeEnum.SYSTEM_NO_AUTH);
            }
            actionRecordUtil.addConversionRecord(id, CrmEnum.CONTACTS, newOwnerUserId, getById(id).getName());
        }
        LambdaUpdateWrapper<CrmContacts> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(CrmContacts::getContactsId, ids);
        wrapper.set(CrmContacts::getOwnerUserId, newOwnerUserId);
        update(wrapper);
        //修改es
        String ownerUserName = UserCacheUtil.getUserName(newOwnerUserId);
        Map<String, Object> map = new HashMap<>();
        map.put("ownerUserId", newOwnerUserId);
        map.put("ownerUserName", ownerUserName);
        updateField(map, ids);
    }

    /**
     * 下载导入模板
     *
     * @param response 联系人id
     * @throws IOException exception
     */
    @Override
    public void downloadExcel(HttpServletResponse response) throws IOException {
        List<CrmModelFiledVO> crmModelFiledList = queryField(null);
        crmModelFiledList.removeIf(model -> Arrays.asList(FieldEnum.FILE, FieldEnum.CHECKBOX, FieldEnum.USER, FieldEnum.STRUCTURE).contains(FieldEnum.parse(model.getType())));
//        crmModelFiledList.removeIf(model -> "籍贯:省/市/区".equals(model.getName()));
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("联系人导入表");
        sheet.setDefaultRowHeight((short) 400);
        CellStyle textStyle = wb.createCellStyle();
        DataFormat format = wb.createDataFormat();
        textStyle.setDataFormat(format.getFormat("@"));
        for (int i = 0; i < crmModelFiledList.size(); i++) {
            CrmModelFiledVO crmModel = crmModelFiledList.get(i);
            if (FieldEnum.DATE.getType().equals(crmModel.getType())) {
                CellStyle dateStyle = wb.createCellStyle();
                DataFormat dateFormat = wb.createDataFormat();
                dateStyle.setDataFormat(dateFormat.getFormat(DatePattern.NORM_DATE_PATTERN));
                sheet.setDefaultColumnStyle(i, dateStyle);
            } else if (FieldEnum.DATETIME.getType().equals(crmModel.getType())) {
                CellStyle dateStyle = wb.createCellStyle();
                DataFormat dateFormat = wb.createDataFormat();
                dateStyle.setDataFormat(dateFormat.getFormat(DatePattern.NORM_DATETIME_PATTERN));
                sheet.setDefaultColumnStyle(i, dateStyle);
            } else {
                sheet.setDefaultColumnStyle(i, textStyle);
            }
            sheet.setColumnWidth(i, 20 * 256);
        }
        HSSFRow titleRow = sheet.createRow(0);
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font font = wb.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 16);
        cellStyle.setFont(font);
        titleRow.createCell(0).setCellValue("联系人导入模板(*)为必填项");
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        titleRow.getCell(0).setCellStyle(cellStyle);
        CellRangeAddress region = new CellRangeAddress(0, 0, 0, crmModelFiledList.size() + 1);
        sheet.addMergedRegion(region);
        try {
            HSSFRow row = sheet.createRow(1);
            for (int i = 0; i < crmModelFiledList.size(); i++) {
                CrmModelFiledVO record = crmModelFiledList.get(i);
                String fieldName = "_" + record.getFieldName();
                fieldName = fieldName.replaceAll("[\\n`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。， 、？]", "");
                //省市区需特殊处理
                if ("_mapAddress".equals(fieldName)) {
                    HSSFCell cell1 = row.createCell(i);
                    cell1.setCellValue("省");
                    HSSFCell cell2 = row.createCell(i + 1);
                    cell2.setCellValue("市");
                    HSSFCell cell3 = row.createCell(i + 2);
                    cell3.setCellValue("区");
                    HSSFSheet hideSheet = wb.createSheet(fieldName);
                    wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
                    int rowId = 0;
                    // 设置第一行，存省的信息
                    Row provinceRow = hideSheet.createRow(rowId++);
                    provinceRow.createCell(0).setCellValue("省列表");
                    List<String> provinceList = getBaseMapper().queryCityList(100000);
                    for (int x = 0; x < provinceList.size(); x++) {
                        Cell provinceCell = provinceRow.createCell(x + 1);
                        provinceCell.setCellValue(provinceList.get(x));
                    }
                    // 将具体的数据写入到每一行中，行开头为父级区域，后面是子区域。
                    Map<String, List<String>> areaMap = CrmExcelUtil.getAreaMap();
                    for (String key : areaMap.keySet()) {
                        List<String> son = areaMap.get(key);
                        Row subRow = hideSheet.createRow(rowId++);
                        subRow.createCell(0).setCellValue(key);
                        for (int x = 0; x < son.size(); x++) {
                            Cell cell = subRow.createCell(x + 1);
                            cell.setCellValue(son.get(x));
                        }
                        // 添加名称管理器
                        String range = CrmExcelUtil.getRange(1, rowId, son.size());
                        Name name = wb.createName();
                        // key不可重复
                        name.setNameName(key);
                        String formula = fieldName + "!" + range;
                        name.setRefersToFormula(formula);
                    }
                    // 省级下拉框
                    CellRangeAddressList provRangeAddressList = new CellRangeAddressList(2, Integer.MAX_VALUE, i, i);
                    String[] arr = provinceList.toArray(new String[]{});
                    DVConstraint provConstraint = DVConstraint.createExplicitListConstraint(arr);
                    HSSFDataValidation provinceDataValidation = new HSSFDataValidation(provRangeAddressList, provConstraint);
                    provinceDataValidation.createErrorBox("error", "请选择正确的省份");
                    sheet.addValidationData(provinceDataValidation);
                    //市 区下拉框
                    for (int x = 2; x < 10000; x++) {
                        CrmExcelUtil.setDataValidation(CrmExcelUtil.getCorrespondingLabel(i + 1), sheet, x, i + 1);
                        CrmExcelUtil.setDataValidation(CrmExcelUtil.getCorrespondingLabel(i + 2), sheet, x, i + 2);
                    }
                } else if ("_mapCity".equals(fieldName)) {
                    HSSFCell cell1 = row.createCell(i+2);
                    cell1.setCellValue("目前就业省");
                    HSSFCell cell2 = row.createCell(i + 3);
                    cell2.setCellValue("目前就业市");
                    HSSFCell cell3 = row.createCell(i + 4);
                    cell3.setCellValue("目前就业区");
                    HSSFSheet hideSheet = wb.createSheet(fieldName);
                    wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
                    int rowId = 0;
                    // 设置第一行，存省的信息
                    Row provinceRow = hideSheet.createRow(rowId++);
                    provinceRow.createCell(0).setCellValue("省列表");
                    List<String> provinceList = getBaseMapper().queryCityList(100000);
                    for (int x = 0; x < provinceList.size(); x++) {
                        Cell provinceCell = provinceRow.createCell(x + 1);
                        provinceCell.setCellValue(provinceList.get(x));
                    }
                    // 将具体的数据写入到每一行中，行开头为父级区域，后面是子区域。
                    Map<String, List<String>> areaMap = CrmExcelUtil.getAreaMap();
                    for (String key : areaMap.keySet()) {
                        List<String> son = areaMap.get(key);
                        Row subRow = hideSheet.createRow(rowId++);
                        subRow.createCell(0).setCellValue(key);
                        for (int x = 0; x < son.size(); x++) {
                            Cell cell = subRow.createCell(x + 1);
                            cell.setCellValue(son.get(x));
                        }
                        // 添加名称管理器
                        String range = CrmExcelUtil.getRange(1, rowId, son.size());
                        Name name = wb.createName();
                        // key不可重复
                        name.setNameName(key+"1");
                        String formula = fieldName + "!" + range;
                        name.setRefersToFormula(formula);
                    }
                    // 省级下拉框
                    CellRangeAddressList provRangeAddressList = new CellRangeAddressList(2, Integer.MAX_VALUE, i, i);
                    String[] arr = provinceList.toArray(new String[]{});
                    DVConstraint provConstraint = DVConstraint.createExplicitListConstraint(arr);
                    HSSFDataValidation provinceDataValidation = new HSSFDataValidation(provRangeAddressList, provConstraint);
                    provinceDataValidation.createErrorBox("error", "请选择正确的省份");
                    sheet.addValidationData(provinceDataValidation);
                    //市 区下拉框
                    for (int x = 2; x < 10000; x++) {
                        CrmExcelUtil.setDataValidation(CrmExcelUtil.getCorrespondingLabel(i + 3), sheet, x, i + 3);
                        CrmExcelUtil.setDataValidation(CrmExcelUtil.getCorrespondingLabel(i + 4), sheet, x, i + 4);
                    }
                } else if ("_mapWifsuu".equals(fieldName)) {
                    HSSFCell cell1 = row.createCell(i+4);
                    cell1.setCellValue("期望就业省");
                    HSSFCell cell2 = row.createCell(i + 5);
                    cell2.setCellValue("期望就业市");
                    HSSFCell cell3 = row.createCell(i + 6);
                    cell3.setCellValue("期望就业区");
                    HSSFSheet hideSheet = wb.createSheet(fieldName);
                    wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
                    int rowId = 0;
                    // 设置第一行，存省的信息
                    Row provinceRow = hideSheet.createRow(rowId++);
                    provinceRow.createCell(0).setCellValue("省列表");
                    List<String> provinceList = getBaseMapper().queryCityList(100000);
                    for (int x = 0; x < provinceList.size(); x++) {
                        Cell provinceCell = provinceRow.createCell(x + 1);
                        provinceCell.setCellValue(provinceList.get(x));
                    }
                    // 将具体的数据写入到每一行中，行开头为父级区域，后面是子区域。
                    Map<String, List<String>> areaMap = CrmExcelUtil.getAreaMap();
                    for (String key : areaMap.keySet()) {
                        List<String> son = areaMap.get(key);
                        Row subRow = hideSheet.createRow(rowId++);
                        subRow.createCell(0).setCellValue(key);
                        for (int x = 0; x < son.size(); x++) {
                            Cell cell = subRow.createCell(x + 1);
                            cell.setCellValue(son.get(x));
                        }
                        // 添加名称管理器
                        String range = CrmExcelUtil.getRange(1, rowId, son.size());
                        Name name = wb.createName();
                        // key不可重复
                        name.setNameName(key+"2");
                        String formula = fieldName + "!" + range;
                        name.setRefersToFormula(formula);
                    }
                    // 省级下拉框
                    CellRangeAddressList provRangeAddressList = new CellRangeAddressList(2, Integer.MAX_VALUE, i, i);
                    String[] arr = provinceList.toArray(new String[]{});
                    DVConstraint provConstraint = DVConstraint.createExplicitListConstraint(arr);
                    HSSFDataValidation provinceDataValidation = new HSSFDataValidation(provRangeAddressList, provConstraint);
                    provinceDataValidation.createErrorBox("error", "请选择正确的省份");
                    sheet.addValidationData(provinceDataValidation);
                    //市 区下拉框
                    for (int x = 2; x < 10000; x++) {
                        CrmExcelUtil.setDataValidation(CrmExcelUtil.getCorrespondingLabel(i + 5), sheet, x, i + 5);
                        CrmExcelUtil.setDataValidation(CrmExcelUtil.getCorrespondingLabel(i + 6), sheet, x, i + 6);
                    }
                } else {
                    HSSFCell cell = row.createCell(i);
                    cell.setCellValue(record.getName() + (record.getIsNull() == 1 ? "(*)" : ""));
                    List<String> setting = record.getSetting().stream().map(Object::toString).collect(Collectors.toList());
                    if (setting != null && setting.size() != 0) {
                        HSSFSheet hidden = wb.createSheet(fieldName);
                        HSSFCell sheetCell = null;
                        for (int j = 0, length = setting.size(); j < length; j++) {
                            String name = setting.get(j);
                            HSSFRow sheetRow = hidden.createRow(j);
                            sheetCell = sheetRow.createCell(0);
                            sheetCell.setCellValue(name);
                        }
                        Name namedCell = wb.createName();
                        namedCell.setNameName(fieldName);
                        namedCell.setRefersToFormula(fieldName + "!$A$1:$A$" + setting.size());
                        CellRangeAddressList regions = new CellRangeAddressList(2, Integer.MAX_VALUE, i, i);
                        DVConstraint constraint = DVConstraint.createFormulaListConstraint(fieldName);
                        HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
                        wb.setSheetHidden(wb.getSheetIndex(hidden), true);
                        sheet.addValidationData(dataValidation);
                    }
                }
            }
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition", "attachment;filename=contacts_import.xls");
            wb.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("联系人模板下载错误：", e);
        } finally {
            wb.close();
        }
    }

    /**
     * 全部导出
     *
     * @param response resp
     * @param search   搜索对象
     */
    @Override
    public void exportExcel(HttpServletResponse response, CrmSearchBO search) {
        List<Map<String, Object>> dataList = queryPageList(search).getList();
        try (ExcelWriter writer = ExcelUtil.getWriter()) {
            List<CrmFieldSortVO> headList = crmFieldService.queryListHead(getLabel().getType());
            headList.forEach(head -> writer.addHeaderAlias(head.getFieldName(), head.getName()));
            writer.merge(headList.size() - 1, "线索信息");
            if (dataList.size() == 0) {
                Map<String, Object> record = new HashMap<>();
                headList.forEach(head -> record.put(head.getFieldName(), ""));
                dataList.add(record);
            }
            writer.setOnlyAlias(true);
            writer.write(dataList, true);
            writer.setRowHeight(0, 30);
            writer.setRowHeight(1, 20);
            for (int i = 0; i < headList.size(); i++) {
                writer.setColumnWidth(i, 20);
            }
            Cell cell = writer.getCell(0, 0);
            CellStyle cellStyle = cell.getCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = writer.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 16);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            //自定义标题别名
            //response为HttpServletResponse对象
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition", "attachment;filename=contacts.xls");
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out);
        } catch (Exception e) {
            log.error("导出联系人错误：", e);
        }
    }

    /**
     * 标星
     *
     * @param id 联系人id
     */
    @Override
    public void star(Integer id) {
        LambdaQueryWrapper<CrmContactsUserStar> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CrmContactsUserStar::getContactsId, id);
        wrapper.eq(CrmContactsUserStar::getUserId, UserUtil.getUserId());
        CrmContactsUserStar star = crmContactsUserStarService.getOne(wrapper);
        if (star == null) {
            star = new CrmContactsUserStar();
            star.setContactsId(id);
            star.setUserId(UserUtil.getUserId());
            crmContactsUserStarService.save(star);
        } else {
            crmContactsUserStarService.removeById(star.getId());
        }
    }

    @Override
    public List<CrmModelFiledVO> information(Integer contactsId) {
        CrmModel crmModel = queryById(contactsId);
        List<String> keyList = Arrays.asList("name", "telephone", "mobile", "email", "post", "address", "nextTime", "remark", "vipPeriods", "afterPurchase", "turnIntroduce", "turnReferral", "refunding", "turnEarlyNumber", "relearn", "suspensionSchooling");
        List<String> fieldBasicNameList = Arrays.asList("姓名", "客户名称", "性别", "年龄");
        List<String> fieldContactNameList = Arrays.asList("电话", "微信", "QQ", "训练营期数", "邮编", "VIP期数");
        List<String> fieldStatusNameList = Arrays.asList("复购", "转介绍", "转介绍人", "休学", "转期", "转前期数", "重修", "重修前期数");
        List<String> fieldDesignNameList = Arrays.asList("学历", "所学专业", "学前职业", "设计水平", "学习状态", "接单状态", "就业薪资", "就业企业", "入职时间", "毕业院校", "毕业时间", "学前薪资", "设计工作年限", "毕业状态", "就业状态", "就业城市", "就业企业规模", "工作照", "入职时间");
        List<String> fieldSystemNameList = Arrays.asList("备注");
        List<String> systemFieldList = Arrays.asList("创建人", "创建时间", "更新时间", "最后跟进时间");
        List<CrmModelFiledVO> crmModelFiledVOS = queryInformation(crmModel, keyList);
        JSONObject object = new JSONObject().fluentPut("customerId", crmModel.get("customerId")).fluentPut("customerName", crmModel.get("customerName"));
        crmModelFiledVOS.add(new CrmModelFiledVO("customerName", FieldEnum.CUSTOMER, "客户名称", 1).setValue(object));
        crmModelFiledVOS.add(new CrmModelFiledVO("relearnPeriods", FieldEnum.TEXT, "重修前期数", 1).setAuthLevel(3).setValue(crmModel.get("relearnPeriods")));
        List<CrmModelFiledVO> filedVOS = crmModelFiledVOS.stream().sorted(Comparator.comparingInt(r -> -r.getFieldType())).peek(r -> {
            r.setFieldType(null);
            r.setSetting(null);
            r.setType(null);
            if (systemFieldList.contains(r.getName())) {
                r.setSysInformation(1);
            } else {
                r.setSysInformation(0);
            }

            if (fieldBasicNameList.contains(r.getName())) {
                r.setTypeField("基本信息");
            } else if (fieldContactNameList.contains(r.getName())) {
                r.setTypeField("联系信息");
            } else if (fieldStatusNameList.contains(r.getName())) {
                r.setTypeField("客户状态");
            } else if (fieldDesignNameList.contains(r.getName())) {
                r.setTypeField("设计类");
            } else if (fieldSystemNameList.contains(r.getName())) {
                r.setTypeField("系统信息");
            } else {
                r.setTypeField("其他信息");
            }

        }).collect(Collectors.toList());
        ICrmRoleFieldService crmRoleFieldService = SpringUtils.getBean(ICrmRoleFieldService.class);
        List<CrmRoleField> roleFieldList = crmRoleFieldService.queryUserFieldAuth(crmModel.getLabel(), 1);
        List<CrmDeptField> deptFieldList = SpringUtils.getBean(ICrmDeptFieldService.class).queryUserFieldAuth(crmModel.getLabel(), 1);
        Map<String, Integer> levelMap = new HashMap<>();
        roleFieldList.forEach(crmRoleField -> {
            levelMap.put(StrUtil.toCamelCase(crmRoleField.getFieldName()), crmRoleField.getAuthLevel());
        });
        deptFieldList.forEach(crmDeptField -> {
            String key = StrUtil.toCamelCase(crmDeptField.getFieldName());
            if(!Optional.ofNullable(levelMap.get(key)).isPresent()){
                levelMap.put(StrUtil.toCamelCase(crmDeptField.getFieldName()), crmDeptField.getAuthLevel());
            }else{
                Integer level = levelMap.get(key);
                if(level.compareTo(crmDeptField.getAuthLevel()) < 0 ){
                    levelMap.put(StrUtil.toCamelCase(crmDeptField.getFieldName()), crmDeptField.getAuthLevel());
                }
            }
        });
        filedVOS.removeIf(field -> (!UserUtil.isAdmin() && Objects.equals(1, levelMap.get(field.getFieldName()))));
        return filedVOS;
    }

    /**
     * 查询文件数量
     *
     * @param contactsId id
     * @return data
     */
    @Override
    public CrmInfoNumVO num(Integer contactsId) {
        CrmContacts crmContacts = getById(contactsId);
        AdminFileService fileService = SpringUtils.getBean(AdminFileService.class);
        List<CrmField> crmFields = crmFieldService.queryFileField();
        List<String> batchIdList = new ArrayList<>();
        if (crmFields.size() > 0) {
            LambdaQueryWrapper<CrmContactsData> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmContactsData::getValue);
            wrapper.eq(CrmContactsData::getBatchId, crmContacts.getBatchId());
            wrapper.in(CrmContactsData::getFieldId, crmFields.stream().map(CrmField::getFieldId).collect(Collectors.toList()));
            batchIdList.addAll(crmContactsDataService.listObjs(wrapper, Object::toString));
        }
        batchIdList.add(crmContacts.getBatchId());
        batchIdList.addAll(crmActivityService.queryFileBatchId(crmContacts.getCustomerId(), getLabel().getType()));
        Map<String, Object> map = new HashMap<>();
        map.put("contactsId", contactsId);
        CrmInfoNumVO infoNumVO = getBaseMapper().queryNum(map);
        infoNumVO.setFileCount(fileService.queryNum(batchIdList));
        return infoNumVO;
    }

    /**
     * 查询文件列表
     *
     * @param contactsId id
     * @return file
     */
    @Override
    public List<FileEntity> queryFileList(Integer contactsId) {
        List<FileEntity> fileEntityList = new ArrayList<>();
        CrmContacts crmContacts = getById(contactsId);
        AdminFileService fileService = SpringUtils.getBean(AdminFileService.class);
        fileService.queryFileList(crmContacts.getBatchId()).forEach(fileEntity -> {
            fileEntity.setSource("附件上传");
            fileEntity.setReadOnly(0);
            fileEntityList.add(fileEntity);
        });
        List<CrmField> crmFields = crmFieldService.queryFileField();
        if (crmFields.size() > 0) {
            LambdaQueryWrapper<CrmContactsData> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmContactsData::getValue);
            wrapper.eq(CrmContactsData::getBatchId, crmContacts.getBatchId());
            wrapper.in(CrmContactsData::getFieldId, crmFields.stream().map(CrmField::getFieldId).collect(Collectors.toList()));
            List<FileEntity> data = fileService.queryFileList(crmContactsDataService.listObjs(wrapper, Object::toString));
            data.forEach(fileEntity -> {
                fileEntity.setSource("联系人详情");
                fileEntity.setReadOnly(1);
                fileEntityList.add(fileEntity);
            });
        }
        List<String> stringList = crmActivityService.queryFileBatchId(crmContacts.getContactsId(), getLabel().getType());
        if (stringList.size() > 0) {
            List<FileEntity> data = fileService.queryFileList(stringList);
            data.forEach(fileEntity -> {
                fileEntity.setSource("跟进记录");
                fileEntity.setReadOnly(1);
                fileEntityList.add(fileEntity);
            });
        }
        return fileEntityList;
    }

    @Override
    public List<SimpleCrmEntity> querySimpleEntity(List<Integer> ids) {
        if (ids.size() == 0) {
            return new ArrayList<>();
        }
        List<CrmContacts> list = query().in("contacts_id", ids).list();
        return list.stream().map(crmContacts -> {
            SimpleCrmEntity simpleCrmEntity = new SimpleCrmEntity();
            simpleCrmEntity.setId(crmContacts.getContactsId());
            simpleCrmEntity.setName(crmContacts.getName());
            return simpleCrmEntity;
        }).collect(Collectors.toList());
    }

    /**
     * 大的搜索框的搜索字段
     *
     * @return fields
     */
    @Override
    public String[] appendSearch() {
        return new String[]{"name", "telephone", "mobile"};
    }

    /**
     * 获取crm列表类型
     *
     * @return data
     */
    @Override
    public CrmEnum getLabel() {
        return CrmEnum.CONTACTS;
    }

    /**
     * 查询所有字段
     *
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryDefaultField() {
        List<CrmModelFiledVO> filedList = crmFieldService.queryField(getLabel().getType());
        filedList.add(new CrmModelFiledVO("lastTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("updateTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("createTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("ownerUserId", FieldEnum.USER, 1));
        filedList.add(new CrmModelFiledVO("createUserId", FieldEnum.USER, 1));
//        filedList.add(new CrmModelFiledVO("dataFrom", FieldEnum.TEXT,1));
        return filedList;
    }

    @Override
    public String getContactsName(int contactsId) {
        return lambdaQuery().select(CrmContacts::getName).eq(CrmContacts::getContactsId, contactsId).oneOpt()
                .map(CrmContacts::getName).orElse("");
    }

    public JSONObject getRecord(Integer fieldId, String fieldName, String formType, String name, Integer type, Integer fieldType, String value) {
        JSONObject object = new JSONObject();
        object.put("fieldId", fieldId);
        object.put("fieldName", fieldName);
        object.put("formType", formType);
        object.put("name", name);
        object.put("type", type);
        object.put("fieldType", fieldType);
        object.put("value", value);
        return object;
    }

    @Override
    public void updateInformation(CrmUpdateInformationBO updateInformationBO) {
        String batchId = updateInformationBO.getBatchId();
        Integer contactsId = updateInformationBO.getId();
        CrmContacts contacts = getById(contactsId);

        //如果直接修改 转前期数 转期不是选择的是则不做更新,如果修改转期 为是 转前期数 必填
        List<JSONObject> refundingList = updateInformationBO.getList().stream().filter(object -> "refunding".equals(object.getString("fieldName"))).collect(Collectors.toList());
        List<JSONObject> turnEarlyNumberList = updateInformationBO.getList().stream().filter(object -> "turnEarlyNumber".equals(object.getString("fieldName"))).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(refundingList)) {
            JSONObject refunding = refundingList.get(0);
            if ("是".equals(refunding.getString("value"))) {
                if (CollectionUtil.isEmpty(turnEarlyNumberList)) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_REFUNDING_IS_TRUE_NUMBER_NEED);
                } else {
                    JSONObject turnEarlyNumber = turnEarlyNumberList.get(0);
                    if (StringUtils.isBlank(turnEarlyNumber.getString("value"))) {
                        throw new CrmException(CrmCodeEnum.CRM_CONTACTS_REFUNDING_IS_TRUE_NUMBER_NEED);
                    }
                }
            } else {
                if (CollectionUtil.isNotEmpty(turnEarlyNumberList)) {
                    turnEarlyNumberList.get(0).put("value", "");
                } else {
                    CrmField field = crmFieldService.lambdaQuery().select(CrmField::getFieldId)
                            .eq(CrmField::getFieldName, "turn_early_number").one();
                    if(field != null){
                        JSONObject object = getRecord(field.getFieldId(), "turnEarlyNumber", "text", "转前期数", 1, 1, "");
                        updateInformationBO.getList().add(object);
                    }
                }
            }
        } else {
            if (CollectionUtil.isNotEmpty(turnEarlyNumberList)) {
                if (!"是".equals(contacts.getRefunding())) {
                    return;
                }
            }
        }

        //如果直接修改 转介绍人 转介绍不是选择的是 则不做更新,如果修改转介绍 为是 转介绍人 必填
        List<JSONObject> turnIntroduceList = updateInformationBO.getList().stream().filter(object -> "turnIntroduce".equals(object.getString("fieldName"))).collect(Collectors.toList());
        List<JSONObject> turnReferralList = updateInformationBO.getList().stream().filter(object -> "turnReferral".equals(object.getString("fieldName"))).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(turnIntroduceList)) {
            JSONObject turnIntroduce = turnIntroduceList.get(0);
            if ("是".equals(turnIntroduce.getString("value"))) {
                if (CollectionUtil.isEmpty(turnReferralList)) {
                    throw new CrmException(CrmCodeEnum.CRM_CONTACTS_TURN_INTRODUCE_IS_TRUE_NUMBER_NEED);
                } else {
                    JSONObject turnReferral = turnReferralList.get(0);
                    if (StringUtils.isBlank(turnReferral.getString("value"))) {
                        throw new CrmException(CrmCodeEnum.CRM_CONTACTS_TURN_INTRODUCE_IS_TRUE_NUMBER_NEED);
                    }
                }
            } else {
                if (CollectionUtil.isNotEmpty(turnReferralList)) {
                    turnReferralList.get(0).put("value", "");
                } else {
                    CrmField field = crmFieldService.lambdaQuery().select(CrmField::getFieldId)
                            .eq(CrmField::getFieldName, "turn_referral").one();
                    if(field != null){
                        JSONObject object = getRecord(field.getFieldId(), "turnReferral", "text", "转介绍人", 1, 1, "");
                        updateInformationBO.getList().add(object);
                    }
                }
            }
        } else {
            if (CollectionUtil.isNotEmpty(turnReferralList)) {
                if (!"是".equals(contacts.getTurnIntroduce())) {
                    return;
                }
            }
        }
        updateInformationBO.getList().forEach(record -> {

            //如果直接修改 转介绍人  转介绍不是选择的是则不做更新

            CrmContacts oldContacts = getById(updateInformationBO.getId());
            Map<String, Object> oldContactsMap = BeanUtil.beanToMap(oldContacts);
            if (record.getInteger("fieldType") == 1) {
                Map<String, Object> crmContactsMap = new HashMap<>(oldContactsMap);
                crmContactsMap.put(record.getString("fieldName"), record.get("value"));
                CrmContacts crmContacts = BeanUtil.mapToBean(crmContactsMap, CrmContacts.class, true);
                //验证电话格式
                if(StringUtils.isNotBlank(crmContacts.getTelephone())){
                    if(!(crmContacts.getTelephone().matches(Const.REG_EXP_MOBILE) || crmContacts.getTelephone().matches(Const.REG_EXP_TELEPHONE))){
                        throw new CrmException(CrmCodeEnum.CRM_REG_EXP_ERROR);
                    }
                }
                actionRecordUtil.updateRecord(oldContactsMap, crmContactsMap, CrmEnum.CONTACTS, crmContacts.getName(), crmContacts.getContactsId());
                update().set(StrUtil.toUnderlineCase(record.getString("fieldName")), record.get("value")).eq("contacts_id", updateInformationBO.getId()).update();
                if ("name".equals(record.getString("fieldName"))) {
                    ElasticUtil.batchUpdateEsData(elasticsearchRestTemplate.getClient(), "contacts", crmContacts.getContactsId().toString(), crmContacts.getName());
                }
            } else if (record.getInteger("fieldType") == 0 || record.getInteger("fieldType") == 2) {

                CrmContactsData contactsData = crmContactsDataService.lambdaQuery().select(CrmContactsData::getValue).eq(CrmContactsData::getFieldId, record.getInteger("fieldId"))
                        .eq(CrmContactsData::getBatchId, batchId).one();
                String value = contactsData != null ? contactsData.getValue() : null;
                String detail = actionRecordUtil.getDetailByFormTypeAndValue(record, value);
                actionRecordUtil.publicContentRecord(CrmEnum.CONTACTS, BehaviorEnum.UPDATE, contactsId, oldContacts.getName(), detail);

                boolean isUpdate = false;
                if ((null == value && null == record.get("value"))) {
                    isUpdate = false;
                } else if (null != value && !value.equals(String.valueOf(record.get("value")))) {
                    isUpdate = true;
                } else if (null != record.get("value") && !String.valueOf(record.get("value")).equals(value)) {
                    isUpdate = true;
                }
                if (isUpdate) {
                    boolean bol = crmContactsDataService.lambdaUpdate()
                            .set(CrmContactsData::getName, record.getString("fieldName"))
                            .set(CrmContactsData::getValue, record.getString("value"))
                            .eq(CrmContactsData::getFieldId, record.getInteger("fieldId"))
                            .eq(CrmContactsData::getBatchId, batchId).update();
                    if (!bol) {
                        CrmContactsData crmContactsData = new CrmContactsData();
                        crmContactsData.setFieldId(record.getInteger("fieldId"));
                        crmContactsData.setName(record.getString("fieldName"));
                        crmContactsData.setValue(record.getString("value"));
                        crmContactsData.setCreateTime(new Date());
                        crmContactsData.setBatchId(batchId);
                        crmContactsDataService.save(crmContactsData);
                    }
                }
            }
            updateField(record, contactsId);
        });
    }

    @Override
    public BasePage<Map<String, Object>> queryBusiness(CrmBusinessPageBO businessPageBO) {
        BasePage<Map<String, Object>> page = getBaseMapper().queryBusiness(businessPageBO.parse(), businessPageBO.getContactsId());
        return page;
    }

    @Override
    public void relateBusiness(CrmRelateBusinessBO relateBusinessBO) {
        crmContactsBusinessService.lambdaUpdate().eq(CrmContactsBusiness::getContactsId, relateBusinessBO.getContactsId()).remove();
        for (Integer businessId : relateBusinessBO.getBusinessIds()) {
            CrmContactsBusiness crmContactsBusiness = new CrmContactsBusiness();
            crmContactsBusiness.setContactsId(relateBusinessBO.getContactsId());
            crmContactsBusiness.setBusinessId(businessId);
            crmContactsBusinessService.save(crmContactsBusiness);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unrelateBusiness(CrmRelateBusinessBO relateBusinessBO) {
        //delete from 72crm_crm_contacts_business where contacts_id = #para(contactsId) and business_id in (#fori(ids))
        crmContactsBusinessService.lambdaUpdate().eq(CrmContactsBusiness::getContactsId, relateBusinessBO.getContactsId())
                .in(CrmContactsBusiness::getBusinessId, relateBusinessBO.getBusinessIds()).remove();
        //UPDATE `72crm_crm_business` SET `contacts_id` = NULL WHERE contacts_id = #para(contactsId) and `business_id`  in (#fori(ids))
        crmBusinessService.lambdaUpdate().set(CrmBusiness::getContactsId, null)
                .eq(CrmBusiness::getContactsId, relateBusinessBO.getContactsId())
                .in(CrmBusiness::getBusinessId, relateBusinessBO.getBusinessIds()).update();
    }

    public List<CrmDataCheckVO> dataCheck(CrmDataCheckBO dataCheckBO) {
        List<CrmDataCheckVO> list = getBaseMapper().dataCheck(dataCheckBO);
        for (CrmDataCheckVO crmDataCheckVO : list) {
            if (crmDataCheckVO.getOwnerUserId() != null) {
                crmDataCheckVO.setOwnerUserName(UserCacheUtil.getUserName(crmDataCheckVO.getOwnerUserId()));
            }
            if (crmDataCheckVO.getContactsId() != null) {
                crmDataCheckVO.setContactsName(Optional.ofNullable(this.getById(crmDataCheckVO.getContactsId())).map(CrmContacts::getName).orElse(null));
            }
        }
        return list;
    }

    /**
     * 根据客户Id获取联系人信息
     *
     * @param customerId
     * @return
     */
    @Override
    public CrmContacts getContactsByCustomerId(Integer customerId) {
        return baseMapper.getContactsByCustomerId(customerId);
    }

    @Override
    public Long comparisonExcel(MultipartFile file, Long ownerUserId, Integer repeatHandling, String vipPeriods) throws IOException {
        UploadExcelBO uploadExcelBO = new UploadExcelBO();
        uploadExcelBO.setOwnerUserId(ownerUserId);
        uploadExcelBO.setUserInfo(UserUtil.getUser());
        uploadExcelBO.setCrmEnum(CrmEnum.COMPARISON_EXCEL);
        uploadExcelBO.setPoolId(null);
        uploadExcelBO.setRepeatHandling(repeatHandling);
        uploadExcelBO.setVipPeriods(vipPeriods);
        Long messageId = SpringUtils.getBean(ComparisonExcelService.class).uploadExcel(file, uploadExcelBO);
        return messageId;
    }
}
